package com.hust.hui.quick.service.repository;

import com.hust.hui.quick.service.dao.DirMapper;
import com.hust.hui.quick.service.domain.DirEntity;
import com.hust.hui.quick.service.exception.IllegalDirException;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Repository;
import org.springframework.util.CollectionUtils;

import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * Created by yihui on 2017/7/16.
 */
@Repository
public class DirRepository {

    @Autowired
    private DirMapper dirMapper;


    /**
     * 应用启动时进行初始化表
     */
    public void init() {
        dirMapper.create();
    }


    /**
     * 新增一条目录
     *
     * @param dirEntity
     * @return
     */
    public long addDir(DirEntity dirEntity) {

        checkDirName(dirEntity.getName());

        checkUserId(dirEntity.getUserId());


        // 判断目录是否存在
        checkDirExists(dirEntity.getUserId(), dirEntity.getParentId(), dirEntity.getName());

        int ans = dirMapper.insert(dirEntity);
        if (ans > 0) {
            return dirEntity.getId();
        } else {
            throw new IllegalDirException("add dir failed!");
        }
    }


    public List<DirEntity> queryDirs(long userId) {
        Map<String, Object> params = new HashMap<>(2);
        params.put("userId", userId);
        params.put("isDeleted", 0);
        return query(params);
    }


    /**
     * 更新目录名
     *
     * @param userId
     * @param parentId
     * @param dirId
     * @param newName
     * @return
     */
    public boolean updateDirName(long userId,
                                 long parentId,
                                 long dirId,
                                 String newName) {

        checkDirName(newName);

        checkDirExists(userId, parentId, newName);


        Map<String, Object> params = new HashMap<>(2);
        params.put("id", dirId);
        params.put("name", newName);
        return update(params);
    }


    /**
     * 移动目录
     *
     * @param userId
     * @param dirId
     * @param newParentId
     * @param dirName
     * @return
     */
    public boolean moveDir(long userId,
                           long dirId,
                           long newParentId,
                           String dirName) {

        Map<String, Object> params = new HashMap<>();
        params.put("id", newParentId);
        if (newParentId > 0) { // 判断新的目录是否存在
            params.put("isDeleted", 0);
            List<DirEntity> dirEntityList = query(params);

            if (dirEntityList.size() == 0) {
                throw new IllegalDirException("dir not exists! dirId: " + newParentId);
            }


            // 修改新的层级
            // fixme 改目录下的子目录层级也应该做出相应的修改
            params.put("level", dirEntityList.get(0).getLevel() + 1);
        } else {
            params.put("level", 0);
        }


        // 判断目录是否已经存在
        checkDirExists(userId, newParentId, dirName);


        // 开始移动
        params.put("id", dirId);
        params.put("parentId", newParentId);
        return update(params);
    }


    public boolean delDirs(List<Long> dirIds) {
        return dirMapper.delete(dirIds) > 0;
    }


    /**
     * 判断目录是否存在
     *
     * @param userId
     * @param parentId
     * @param name
     * @return
     */
    private boolean containDirName(long userId, long parentId, String name) {
        Map<String, Object> params = new HashMap<>();
        if (parentId == 0L) { // 根目录时
            params.put("userId", userId);
            params.put("level", 0);
        } else {
            params.put("parentId", parentId);
        }

        params.put("name", name);
        params.put("isDeleted", 0);

        List<DirEntity> res = query(params);
        return !CollectionUtils.isEmpty(res);
    }


    private boolean update(Map<String, Object> params) {
        if (params.containsKey("id")) {
            return dirMapper.update(params) > 0;
        }

        throw new IllegalDirException("please select update dirId!");
    }


    public List<DirEntity> query(Map<String, Object> params) {
        if (params.containsKey("id") || params.containsKey("parentId") || params.containsKey("userId")) {
            return dirMapper.query(params);
        }

        throw new IllegalDirException("query dir should select dirId/parentDirId/userId!");
    }


    private void checkDirName(String name) {
        if (name == null || name.length() > 20) {
            throw new IllegalDirException("dir name should not be null or dir name's length should less then 20!");
        }
    }


    private void checkUserId(long userId) {
        if (userId <= 0) {
            throw new IllegalDirException("dir should be related to a user!");
        }
    }


    private void checkDirExists(long userId, long dirId, String name) {
        if (containDirName(userId, dirId, name)) {
            throw new IllegalDirException(name + " has already exists!");
        }
    }
}
